const WebSocketServer = require("ws").Server;

/**
 * 启动WebSocket监听
 * @param config
 */
const clientMap = new Map();
/**
 * 用户上线
 * @param msg
 * @param ws
 */
function addUser(msg, ws) {
	console.log(`用户上线 : ${msg.userNow}`);
	if(clientMap.has(msg.userNow)) {
		clientMap.get(msg.userNow).close();
		clientMap.delete(msg.userNow);
	} else {
		//给所有已存在的客户端推送用户上线消息
		clientMap.forEach(function(value){
			_send(value, JSON.stringify({
				serverType : 2,
				user : {username : msg.userNow}
			}));
		});
	}
	clientMap.set(msg.userNow, ws);
	//客户端连接以后, 向客户端推送当前在线用户列表
	sendUserList(ws);
}
/**
 * 用户下线
 * @param username
 */
function removeUser(username) {
	console.log(`用户下线 : ${username}`);
	let ws = clientMap.get(username);
	if(ws && !ws.isClosed) {
		ws.close();
	}
	clientMap.delete(username);
	clientMap.forEach(function(value){
		_send(value, JSON.stringify({
			serverType : 3,
			user : {username : username}
		}));
	});
}
/**
 * 推送用户列表
 * @param ws
 */
function sendUserList(ws) {
	var users = [];
	clientMap.forEach(function(value, key){
		users.push({username:key});
	});
	_send(ws, JSON.stringify({users : users,serverType:0}));
}
/**
 * 普通消息推送
 * @param msg
 */
function sendMessage(msg) {
	var message = {
		serverType : 1,
		content : msg.content,
		from : msg.userNow
	};
	msg.target.forEach(function(user){
		_send(clientMap.get(user.username), JSON.stringify(message));
	});
}

function _send(ws, msg) {
	try {
		ws.send(msg);
	} catch (err) {
		console.error("WebSocket消息推送错误!",err);
	}
}
/**
 * 创建WebSocket服务端
 */
function createWebSocket() {
	let config = require("../statics/LoadConfig").WebSocket;
	const server = new WebSocketServer(config);
	console.log(`WebSocket服务监听 : 端口${config.port}`);
	server.on("connection", ws => {
		//连接以后第一次消息推送要告诉服务器当前的用户是谁
		console.log("客户端连接成功...");
		/*
		* 客户端消息类型(clientType)列表
		* 0 - 新建 {userNow:"当前用户"}
		* 1 - 消息推送 {target:[user1,user2...], content:"xxx"}
		* 2 - 注销 {userNow:"当前用户"}
		* */
		ws.on("message", message => {
			var msg = JSON.parse(message);
			switch(msg.clientType) {
				case 0 : addUser(msg, ws); break;
				case 1 : sendMessage(msg); break;
				case 2 : removeUser(msg.userNow); break;
				default :
					console.warn(`不能识别的状态标识 - ${msg.type}`);
			}
		});
	});
}
module.exports = {
	createServer : createWebSocket,
	clientMap : clientMap
};